单片机板有8个输入信号以及若干个输出信号。客户提出要求,希望能通过上位机来配置这8个信号的逻辑关系实现与或操作。头大,不知道该怎么实现。想过如下办法:
1,上位机传递输入信号的序号,然后将所有逻辑关系按序号排出来,将逻辑关系序号也发给单片机,单片机按需要去反推逻辑关系。但是可能的逻辑关系也太多了...
因为只有与和或两种逻辑关系,有群友指出有2^8种排列。
2,上位机发送输入信号的序号,然后再发送几组数据,每组数据包含两个参与操作的信号打序号,再包含一个逻辑关系。这样的话,需要上位机先推算出运算打先后顺序。上位机这里有点麻烦。
3,上位机直接将逻辑运算发送给单片机,包括括号以及运算符,这样上位机就简单了,但是单片机这里就很难了。
如果单片机收到的是类似“x1 && (x2 || x3)"这样的字符串,能否直接转化为可执行语句来执行?
请大家给个思路。
最近编辑记录 Gentlepig (2023-10-11 14:49:11)
离线
传真值表呗,
8in 8out 也就256字节
离线
传真值表呗,
8in 8out 也就256字节
输入是8个,输出不确定,可能更多。
离线
可以用第3种方法 关键字 后缀表达式
这里要用到 栈 ,前提是上位机发送过来的句子是完整的。以下是复制过来的,可以参考一下。
1、首先从左到右扫描每一个字符。如果扫描到的字符是操作数(如a、b等),就直接将操作数push进操作数栈中。
2、如果扫描到的字符是一个操作符,分三种情况:
(1) 如果操作符栈是空的,直接将操作符push到操作符栈中。
(2) 如果该操作符的优先级大于操作符栈栈顶的操作符,就直接将操作符push到操作符栈中。(因为该操作符运算会比栈中的优先级低的先进行运算)
(3)如果该操作符为+、-、*、/等且优先级低于栈顶的操作符,就将栈顶的操作符pop, 直到该操作符的优先级大于栈顶端的操作符,将扫描到的操作符push到栈中。
3、如果遇到的操作符是左括号"(”,就直接将该操作符push到操作符栈中。
4、如果扫描到的操作符是右括号“)”,将操作符栈中的操作符(pop)且操作数栈中出栈两个元素进行运算,运算完之后再push回操作数栈,直到遇见左括号“(”,最后将操作符栈中的左括号pop掉。
5、如果输入的中缀表达式已经扫描完了,但是操作符栈中仍然存在操作符的时候,我们应该将操作符栈中的操作符pop,然后进行操作数栈的运算。
离线
4610 说:传真值表呗,
8in 8out 也就256字节输入是8个,输出不确定,可能更多。
线性的,不是指数关系
32个输出 表1kb
离线
他是要你实现一个 PLC 啊
离线
用3楼说的方法就可以了,这是非常经典的计算表达式的算法
离线
做法的决定,要看需求。
如果可变逻辑中可以转变成单线顺序计算,则可以以“【INx】【运算符enum】【INx】【运算符enum】。。。”形式下发给单片机运行,执行机构以循环就可以算结果。较为简单。
如果可变逻辑中包含类似(INx + INx) * (INx + INx)这种计算,这个在编译器领域叫做未决表达式,计算中途需要临时存储,需要分配寄存器或临时栈变量。这种较为复杂需要编译行为,最好在上机做,要有临时变量的表示手段,需要以类似“【INx】【运算符enum】【INx】【变量x】。。。【变量x】【运算符enum】【变量x】“形式下发单片机运行,执行机需要有几个变量槽位。
离线
字符串解析呗+递归
离线
感谢各位。
关于1里的真值表,我是没搞明白的,分别用1和0表示输入信号的有无,8个输入信号的话,组合就是2^8=256种。那么需要上位机算出这种比如(x1||x2)&&(x3||x4)这种情况下,对应的8个输入有那几种组合,如何输入满足的话,就控制输出。
问了gpt,列出来上式的真值表:
x1 | x2 | x3 | x4 | Output
---------------------------
0 | 0 | 0 | 0 | 0
0 | 0 | 0 | 1 | 1
0 | 0 | 1 | 0 | 1
0 | 0 | 1 | 1 | 1
0 | 1 | 0 | 0 | 0
0 | 1 | 0 | 1 | 1
0 | 1 | 1 | 0 | 1
0 | 1 | 1 | 1 | 1
1 | 0 | 0 | 0 | 0
1 | 0 | 0 | 1 | 1
1 | 0 | 1 | 0 | 1
1 | 0 | 1 | 1 | 1
1 | 1 | 0 | 0 | 1
1 | 1 | 0 | 1 | 1
1 | 1 | 1 | 0 | 1
1 | 1 | 1 | 1 | 1
可以看到output是1的就有13项,那么我需要判断输入信号是否是这13项里的其中一个,是的话,就满足。
这种方法的话,需要上位机计算出真值表里output为1的项目,把对应的输入状态,发给单片机吧?比如上式,就需要将
x1 | x2 | x3 | x4 | Output
---------------------------
0 | 0 | 0 | 1 | 1
0 | 0 | 1 | 0 | 1
0 | 0 | 1 | 1 | 1
0 | 1 | 0 | 1 | 1
0 | 1 | 1 | 0 | 1
0 | 1 | 1 | 1 | 1
1 | 0 | 0 | 1 | 1
1 | 0 | 1 | 0 | 1
1 | 0 | 1 | 1 | 1
1 | 1 | 0 | 0 | 1
1 | 1 | 0 | 1 | 1
1 | 1 | 1 | 0 | 1
1 | 1 | 1 | 1 | 1
这些发给单片机去进行判断吧?
这样倒是简单些,但是实际应该把8个输入都考虑进去,这样最后就是就是一种输出结果可能对应着非常多的输入情况,比如几十个。
又想了想,应该真值表里的256项都写入单片机。单片机里利用switch()判断输入是否在真值表里对应的output是否为1,为1的话,说明输入满足逻辑关系。
最近编辑记录 Gentlepig (2023-10-12 14:32:40)
离线
Gentlepig 说:4610 说:传真值表呗,
8in 8out 也就256字节输入是8个,输出不确定,可能更多。
线性的,不是指数关系
32个输出 表1kb
没明白这里为啥是1kb?
输入的每种逻辑关系,只对应一种输出形式。所以表应该还是按输入的数量8来决定大小吧?输出只是一个4字节变量来控制32个输出,这样?
离线
对于方法3,别墅业主群里很多群友推荐了。其中有朋友推荐了c4.c,我看到简介里写的c in four function。我以为是四则运算呢?结果晚上刷知乎搜c4.c才知道是实现了编译器...虽然里边也有四则运算符,也有与或逻辑运算符,但是我觉得对于我来说内容有深度了...
搜 使用栈完成算术表达式 搜到这么一篇文章,觉得不多:
https://www.cnblogs.com/inghzhang/p/3901334.html
还没仔细看。
最近编辑记录 Gentlepig (2023-10-12 16:25:47)
离线
@Gentlepig
才发现gpt给的真值表不对...
(x1|x2)&(x3|x4),就是1和2中有一个输入有效,且3和4中有一个输入有效,则满足条件。
结果发现2、3、4行,x1和x2都是零的情况下,out为1了...
离线
@Gentlepig
对,8个输入决定了有256种状态,32路输出即4byte,相乘=1kb
既然是真值表,直接根据输入算出储存的位置就是了
o = b^c
a b c o
0 0 0 0
0 0 1 1
0 1 0 1
0 1 1 0
1 0 0 0
1 0 1 1
1 1 0 1
1 1 1 0
map = {0, 1, 1, 0, 0, 1, 1, 0}
o = map[a<<2 | b<<1 | c]
mcu上处理多简单
离线
@4610
可是,单片机c语言没有map这种数据结构啊...
另外的问题就是,上位机如何根据输入逻辑关系,计算出真值表来...
-------------------------------------
好像有一点明白了,这是上位机计算真值表的方式,上位机枚举出256种组合,然后代入到表达式里看结果。
最近编辑记录 Gentlepig (2023-10-13 09:02:40)
离线
@Gentlepig
不需要map,普通的线性表,数组表示
3in:map[8]
8in:map[256]
离线
可以通过多维数字实现,定义一个多维数组uint32 map[2][2][2][2][2][2][2][2];上位机生成遍历数值,不就行了,8路输入,依次填入下标,输出值完成,最多是1K的真值表,搞定
离线
可以通过多维数字实现,定义一个多维数组uint32 map[2][2][2][2][2][2][2][2];上位机生成遍历数值,不就行了,8路输入,依次填入下标,输出值完成,最多是1K的真值表,搞定
看不懂这个map[2][2][2][2][2][2][2][2],每一个[2]对应一个输入的0和1两种状态吗?
依次填入下标,这句话也没看明白。是将遍历输入值,代入逻辑表达式吗?
离线
上位机解析输入表达式,然后把256种输入结果全算出来,然后凑成真值表发给下位机,下位机最差的情况就是256种情况全判断。上位机负责解析表达式和计算真值表,下位机就解析真值表。解析表达式就用c4.c,加减乘除运算不需要,只用到与和或。
最近编辑记录 skrlaoshiren (2023-10-13 14:50:34)
离线
@Gentlepig
不需要map,普通的线性表,数组表示
3in:map[8]
8in:map[256]
明白了,感谢。
@skrlaoshiren @小智
感谢。
最近编辑记录 Gentlepig (2023-10-13 15:11:22)
离线
https://blog.csdn.net/crr411422/article/details/130306750
按这个文章里的代码抄了一遍,没用malloc申请栈空间,而是用了固定数组,把浮点数变量改成了uint8类型,在pc上gcc编译后,可以运行进行整数四则运算。
又将里边的“+-*/”改成了“&|”,可以进行逻辑运算。
$ ./test5
Enter an infix expression: 1&1
infix notation: 1&1
Postfix notation: 1 1 &
Result: 1
$ ./test5
Enter an infix expression: 1&(0|1)
infix notation: 1&(0|1)
Postfix notation: 1 0 1 | &
Result: 1
$ ./test5
Enter an infix expression: (1|1)&(0|1)
infix notation: (1|1)&(0|1)
Postfix notation: 1 1 | 0 1 | &
Result: 1
$ ./test5
Enter an infix expression: (0|1)&(1&0)
infix notation: (0|1)&(1&0)
Postfix notation: 0 1 | 1 0 & &
Result: 0
$ ./test5
Enter an infix expression: (0|1)&(1|0)
infix notation: (0|1)&(1|0)
Postfix notation: 0 1 | 1 0 | &
Result: 1
最近编辑记录 Gentlepig (2023-10-14 15:00:04)
离线
移植这个函数,返回指定引脚电平:
uint8_t get_pin_value(char pin)
{
switch (pin) {
case '1': return 1;
case '2': return 0;
case '3': return 1;
case '4': return 0;
case '5': return 1;
case '6': return 0;
case '7': return 0;
case '8': return 0;
default: break;
}
return 0;
}
计算表达式算法:
#include <stdint.h>
#include <stdbool.h>
#define STACK_SIZE 64
static char stkbuf[STACK_SIZE];
static int stk_top_idx = -1;
static int stk_size(void)
{
return stk_top_idx + 1;
}
static char stk_top(void)
{
if (stk_top_idx < 0)
return 0;
return stkbuf[stk_top_idx];
}
static void stk_push(char chr)
{
if (stk_top_idx >= (STACK_SIZE - 1))
return;
stkbuf[++stk_top_idx] = chr;
}
static void stk_pop(void)
{
if (stk_top_idx >= 0)
stk_top_idx--;
}
static void stk_clear(void)
{
stk_top_idx = -1;
}
#define RPN_BUF_SIZE 64
static char rpnbuf[RPN_BUF_SIZE];
static int rpn_cnt = 0;
bool reverse_polish_notatio_append_chr(char chr)
{
bool ok;
if (chr == '(') {
stk_push(chr);
}
else if (chr == ')') {
ok = false;
while (stk_size() > 0) {
chr = stk_top();
stk_pop();
if (chr == '(') {
ok = true;
break;
}
rpnbuf[rpn_cnt++] = chr;
}
if (!ok)
return false;
}
else if (chr == '|' || chr == '&') {
if (stk_size() > 0) {
char chr_top = stk_top();
if (chr_top != '(') {
stk_pop();
rpnbuf[rpn_cnt++] = chr_top;
}
stk_push(chr);
}
else {
stk_push(chr);
}
}
else if ((chr >= '1') && (chr <= '8')) {
rpnbuf[rpn_cnt++] = chr;
}
else {
return false;
}
return true;
}
bool run_exp(const char *exp, uint8_t *result)
{
int i;
char chr, v1, v2, v;
uint8_t flag_result = 0x80;
rpn_cnt = 0;
stk_clear();
while ((chr = exp[0])) {
switch (chr) {
case 'x':
chr = exp[1];
if ((chr < '1') && (chr > '8'))
return false;
if (!reverse_polish_notatio_append_chr(chr))
return false;
exp += 2;
break;
case '&':
case '|':
if (exp[1] != chr)
return false;
if (!reverse_polish_notatio_append_chr(chr))
return false;
exp += 2;
break;
case '(':
case ')':
if (!reverse_polish_notatio_append_chr(chr))
return false;
exp++;
break;
case ' ':
exp++;
break;
default:
break;
}
}
stk_clear();
for (i = 0; i < (int)rpn_cnt; i++) {
chr = rpnbuf[i];
if (chr >= '1' && chr <= '8') {
stk_push(chr);
}
else if ((chr == '|') || (chr == '&')) {
if (stk_size() <= 0)
return false;
v2 = stk_top();
stk_pop();
if (stk_size() <= 0)
return false;
v1 = stk_top();
stk_pop();
if ((v2 & flag_result) == 0)
v2 = get_pin_value(v2);
if ((v1 & flag_result) == 0)
v1 = get_pin_value(v1);
v1 &= ~flag_result;
v2 &= ~flag_result;
v = (chr == '|') ? v1 || v2 : v1 && v2;
stk_push(flag_result | v);
}
}
if (stk_size() == 1) {
*result = (stk_top() & 0x7f);
return true;
}
return false;
}
测试:
int main(int argc, char *argv[])
{
const char *exp = "(((x1 || x2 && x3)) && (x4 || x5))";
uint8_t result;
if (run_exp(exp, &result)) {
printf("rst: %d\n", result);
}
else {
printf("calc fail\n");
}
return 0;
}
输出结果:
rst: 1
离线
@kin
这是专门为了我的需求写了个程序?太感谢了。
-----------------------------------
因为没有注释,有不少地方没看明白,比如各函数的用途,rpnbuf[ ]数组的用途。
reverse_polish_nnotatio_append_char()这个函数,
如果给的是'(',则压入stk里;
如果是')',则从stk里取出数据放到rpnbuf里;
如果是'&'或者'|',如果栈里没数据,则入栈,如果有数据,取栈顶数据,如果是'(',则将符号入栈,否则,将栈顶字符串出栈,存到rpnbuf数组里,不知道这里为什么要存到rpnbuf里。
如果是字符1-8,则直接存到rpnbuf里。
感觉rpnbuf像是完成后缀表达式的存放位置,但不确定。
run_exp( )函数里也有不明白的地方:
while((chr = exp[0])){...}这里只是判断下表达式的第一个字符吗?(这个明白了,while循环里有exp+=2,这样就会遍历整个输入字符串了)
那么这个while循环里,就会把输入表达式里的‘0-9, & , | ( )'分别代入到reverse_polish_notatio_append_chr( )函数里去处理
根据我在上一段落分析,‘0-9’是存到rpnbuf数组里的,‘(xxxx)'括号里的内容,也会存到rpnbuf里。
我的理解是,rpnbuf数组存放的是后缀表达式,但没看明白什么时候把逻辑符号放进去的。而stk是中缀转后缀时存放临时数据的,比如有括号情况下,将左括号及数据先放到stk里,如果再遇到右括号,则将数据从stk里取出来放到rpnbuf数组里。
最近编辑记录 Gentlepig (2023-10-16 10:47:13)
离线
通过spi不行吗
离线
@Gentlepig
抱歉,我那代码可能写得不太好,也欠缺相关注释。你的理解是对的,rpnbuf储存的就是后缀表达式。
首先建立一个空栈和用来储存后缀表达式的缓冲区,然后遍历整个字符串,根据以下原则做处理:
遇到操作数(这里是x1、x2和x3之类),直接将x后面的字符(如'1'、'2'、'3'等)追加到rpnbuf中。
遇到'(',将其入栈。
遇到')',将栈顶元素依次弹出并追加到rpnbuf中,直到遇到')',然后将'('从栈中弹出。
遇到运算符(这里是||和&&,但是为方便后续处理,储存的时候只储存'|'和'&'):
1、如果栈为空或者栈顶是'(',则直接将当前运算符入栈。。
2、如果该运算符的优先级高于栈顶运算符,则直接将其入栈。
3、如果该运算符的优先级低于或等于栈顶运算符,则将栈顶运算符弹出并追加到rpnbuf中,然后将当前运算符入栈。
由于本案例中只涉及'||'和'&&'这两个运算符,并且它们的优先级是相等的,因此我的代码里并没有优先级判定这部分代码,也就是说,在上面的”遇到运算符“的处理中,只处理了第1点和第3点。
对于rpnbuf的处理:
先建立一个空栈,然后按顺序遍历后缀表达式(即rpnbuf)的每个字符:
遇到操作数时,将其入栈。
遇到操作符时,从栈顶依次取出2个操作数进行计算,并将计算结果重新入栈。
遍历完后缀表达式后,栈中的唯一元素就是最终的计算结果。
另外,因为本案例中,表达式中的操作数是个不确定的值,需要从芯片引脚获取电平来确定实际的值,所以在处理rpnbuf操作数的时候,需要标记这个操作数到底是中间运算结果还是需要从芯片引脚读取。我的代码只做了个简单的处理,就是如果是中间运算结果,那就位或0x80(即最高位置1),如果直接是'1'~'8',那就从芯片引脚中取电平来确定这个值是0还是1,根据最高位来判定是直接计算还是从芯片引脚读取电平。
不知道我说明白了没有,希望能对你有用。关于中缀表达式转后缀表达式的方法,网上也有其他相关资料可以参考一下。
离线
@kin 感谢,讲得很详细了,使我进一步加深了对栈和后缀表达式的理解。
最近编辑记录 Gentlepig (2023-10-17 09:23:35)
离线
上位机直接选个支持eval的语言就完事了…
离线
啥也不想说,直接看代码
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
// str: x1&&(x2||x3)&&(x4||x5)
// planA
// ra0 = X3 || X2
// ra1 = ra0 && x1
// ra0 = x4 || x5
// ra1 = ra0 && ra1
// planB
// ra0 = X3 || X2
// ra1 = x4 || x5
// ra0 = ra0 && ra1
// ra0 = ra0 && x1
/*
x1&&(x2||(x3&&x4))&&(x5||x6)
ra1= x3 && x4
ra0=ra1 || x2
ra1= x5 || x6
ra0=ra1 && ra0
ra0=ra0 && x1
X1
X2
X3
POP -> X3
POP -> X2
X1
ra0
X5
POP -> X5
X1
ra0
I_LOAD X1
I_PUSH
I_LOAD X2
I_PUSH
I_LOAD X3
I_PUSH
I_LOAD X4
I_AND1
ra1 = x3 && x4
I_OR1
ra0 = ra1 || x2
I_PUSH
I_LOAD X5
I_PUSH
I_LOAD X6
I_OR1
ra1 = X5 || x6
I_AND1
ra0 = ra1 && ra0
I_AND1
ra0=ra0 && X1
I_PUSH
*/
#define is_letter(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
#define is_num(c) (c >= '0' && c <= '9')
#define is_id(c) (is_letter(c) || )
enum{
STA_IDLE,
STA_ID,
STA_AND,
STA_OR,
STA_LPAR,
STA_RPAR,
STA_EOL,
}sta;
enum{
I_PUSH,
// I_POP,
I_ENTER,
I_EXIT,
I_LOAD_A0,
I_LOAD_A1,
I_AND1_A0,
I_AND1_A1,
I_OR1_A0,
I_OR1_A1,
I_AND2_RA0_X_X,
I_AND2_RA0_RA0_X,
I_AND2_RA0_RA1_X,
I_AND2_RA0_RA1_RA0,
I_AND2_RA0_RA0_RA1,
// I_AND2_RA0_RA1_RA1,
I_AND2_RA1_X_X,
I_AND2_RA1_RA0_X,
I_AND2_RA1_RA1_X,
I_AND2_RA1_RA1_RA0,
// I_AND2_RA1_RA0_RA1,
I_OR2_RA0_X_X,
I_OR2_RA0_RA0_X,
I_OR2_RA0_RA1_X,
I_OR2_RA0_RA1_RA0,
I_OR2_RA0_RA0_RA1,
// I_OR2_RA0_RA1_RA1,
I_OR2_RA1_X_X,
I_OR2_RA1_RA0_X,
I_OR2_RA1_RA1_X,
I_OR2_RA1_RA1_RA0,
I_OR2_RA1_RA0_RA1,
// I_OR2_RA1_RA1_RA1,
I_UIMP, // end
};
struct {
int t;
int i;
} lex_list[1024];
union{
uint32_t code;
struct{
unsigned char op;
unsigned char a0;
unsigned char a1;
}i;
}code_list[100];
union{
uint32_t code;
struct{
unsigned char op;
unsigned char a0;
unsigned char a1;
}i;
}opt_code_list[100];
int lex_list_i;
int code_list_i;
int opt_code_list_i;
int g_parse_i;
static void parse(void);
static void opt(int lev,int ra_i,int init);
static void prt(int lev,int ra_i);
static int vm(void);
int main(int argc,const char** argv){
int c;
uint32_t id;
int res = 0;
int size = 1024;
char* buff = (char*)malloc(size);
int tmp_c_i = 0;
lex_list_i = 0;
code_list_i = 0;
sta = STA_IDLE;
if(NULL == fgets(buff,size,stdin)){
return 0;
}
// sprintf(buff,"x1&&(x2||(x3&&x4))&&(x5||x6)\n");
printf("str: %s\n",buff);
// buff[strlen(buff)] = '\n';
while(tmp_c_i <= strlen(buff)){
c = buff[tmp_c_i];
tmp_c_i++;
// printf("c: %c(0x%x) sta: %d\n",c,c,sta);
// printf("c: %c(0x%x) sta: %d\n",c,c,sta);
retry:
if(c == '\r' || c == ' ' || c == '\t'){continue;}
switch(sta){
case STA_IDLE:
id = 0;
// if(is_letter(c)){
if(c == 'x'){
// id = c;
sta = STA_ID;
// }else if(is_num(c)){
// id = c;
// sta = STA_ID;
}else if(c == '&'){
sta = STA_AND;
}else if(c == '|'){
sta = STA_OR;
}else if(c == '('){
lex_list[lex_list_i].t = STA_LPAR;
lex_list[lex_list_i].i = 0;
lex_list_i++;
}else if(c == ')'){
lex_list[lex_list_i].t = STA_RPAR;
lex_list[lex_list_i].i = 0;
lex_list_i++;
}else if(c == '\n'){
goto input_ok;
}else{
// error
}
break;
case STA_ID:
// if(is_id(c)){
if(is_num(c)){
id = id * 10 + c - '0';
}else{
printf("sta: STA_ID lex_list_i: %d id: %d\n",lex_list_i,id);
lex_list[lex_list_i].t = STA_ID;
lex_list[lex_list_i].i = id;
lex_list_i++;
sta = STA_IDLE;
goto retry;
}
break;
case STA_AND:
if(c == '&'){
printf("sta: STA_AND\n");
lex_list[lex_list_i].t = STA_AND;
lex_list[lex_list_i].i = 0;
lex_list_i++;
sta = STA_IDLE;
}else{
// error
}
break;
case STA_OR:
if(c == '|'){
// printf("sta: STA_OR\n");
lex_list[lex_list_i].t = STA_OR;
lex_list[lex_list_i].i = 0;
lex_list_i++;
sta = STA_IDLE;
}else{
// error
}
break;
default:
break;
}
// refresh();
}
input_ok:
free(buff);
printf("parse lex_list_i:%d\n",lex_list_i);
g_parse_i = 0;
if(lex_list_i <= 0){
// error
return -1;
}
lex_list[lex_list_i].t = STA_EOL;
lex_list[lex_list_i].i = 0;
lex_list_i++;
printf("=parse==================================================================================\n");
parse();
printf("=prt==================================================================================\n");
prt(0,0);
// return 0;
printf("opt code_list_i:%d\n",code_list_i);
printf("=opt==================================================================================\n");
opt(0,0,1);
opt_code_list[opt_code_list_i].i.op = I_UIMP;
printf("set opt_code_list[%d] to I_UIMP\n",opt_code_list_i);
opt_code_list_i++;
printf("=vm==================================================================================\n");
res = vm();
printf("return %d\n",res);
// while(1);
return 0;
}
static void parse(void){
static int s_lpar_cnt = 0;
// printf("parse g_parse_i:%d lex_list[g_parse_i].t:%d lex_list_i: %d code_list_i:%d\n",g_parse_i,lex_list[g_parse_i].t,lex_list_i,code_list_i);
// refresh();
if(g_parse_i > lex_list_i){
return;
}
if(lex_list[g_parse_i].t == STA_EOL){
// printf("parse g_parse_i:%d lex_list[g_parse_i].t == STA_EOL code_list_i:%d\n",g_parse_i,code_list_i);
return;
}
if(lex_list[g_parse_i].t == STA_ID){
// printf("parse g_parse_i:%d lex_list[g_parse_i].t == STA_ID code_list_i:%d lex_list[g_parse_i].i:%d\n",g_parse_i,code_list_i,lex_list[g_parse_i].i);
// refresh();
code_list[code_list_i].i.op = I_LOAD_A0;
code_list[code_list_i].i.a0 = lex_list[g_parse_i].i;
code_list_i++;
g_parse_i++;
}else if(lex_list[g_parse_i].t == STA_AND){
// printf("parse g_parse_i:%d lex_list[g_parse_i].t == STA_AND code_list_i:%d\n",g_parse_i,code_list_i);
// refresh();
code_list[code_list_i].i.op = I_PUSH;
code_list_i++;
g_parse_i++;
parse();
// printf("parse g_parse_i:%d lex_list[g_parse_i].t == I_AND1 code_list_i:%d\n",g_parse_i,code_list_i);
code_list[code_list_i].i.op = I_AND1_A0;
code_list_i++;
}else if(lex_list[g_parse_i].t == STA_OR){
// printf("parse g_parse_i:%d lex_list[g_parse_i].t == STA_OR\n",g_parse_i);
// refresh();
code_list[code_list_i].i.op = I_PUSH;
code_list_i++;
g_parse_i++;
parse();
code_list[code_list_i].i.op = I_OR1_A0;
code_list_i++;
}else if(lex_list[g_parse_i].t == STA_LPAR){
// printf("parse g_parse_i:%d lex_list[g_parse_i].t == STA_LPAR\n",g_parse_i);
// refresh();
// code_list[code_list_i].i.op = I_PUSH;
// code_list_i++;
code_list[code_list_i].i.op = I_ENTER;
code_list_i++;
g_parse_i++;
s_lpar_cnt++;
parse();
if(lex_list[g_parse_i].t != STA_RPAR){
// error
}
code_list[code_list_i].i.op = I_EXIT;
code_list_i++;
return;
}else if(lex_list[g_parse_i].t == STA_RPAR){
// printf("parse g_parse_i:%d lex_list[g_parse_i].t == STA_RPAR\n",g_parse_i);
// refresh();
if(s_lpar_cnt == 0){
// error
}
s_lpar_cnt--;
// code_list[code_list_i].i.op = I_POP;
// code_list_i++;
g_parse_i++;
return;
}else{
// error
}
parse();
}
static void prt(int lev,int ra_i){
static int pc = 0;
while(1){
// printf("opt pc:%d code_list[pc].i.op: %d code_list_i: %d\n",pc,code_list[pc].i.op,code_list_i);
// refresh();
if(pc > code_list_i){
return;
}
switch(code_list[pc].i.op){
case I_PUSH:
printf("I_PUSH\n");
break;
// case I_ENTER:
// printf("I_ENTER\n");
// break;
// case I_EXIT:
// printf("I_EXIT\n");
// // return;
// break;
case I_LOAD_A0:
printf("I_LOAD X%d\n",code_list[pc].i.a0);
break;
case I_AND1_A0:
printf("I_AND1\n");
break;
case I_OR1_A0:
printf("I_OR1\n");
break;
// case I_AND2:
// break;
// case I_OR2:
// break;
case I_UIMP:
return;
break;
default:
break;
}
pc++;
}
}
static void opt(int lev,int ra_i,int init){
static int pc = 0;
static struct{
unsigned char is_ra;
unsigned char a0;
} stack[100],cur_ra={1,0};
static int ra0_isused=0;
static int ra1_isused=0;
static int stack_pos_start = (sizeof(stack)/sizeof(stack[0]));
static int stack_pos_i = (sizeof(stack)/sizeof(stack[0]));
if(init){
ra0_isused=0;
ra1_isused=0;
stack_pos_start = (sizeof(stack)/sizeof(stack[0]));
stack_pos_i = (sizeof(stack)/sizeof(stack[0]));
cur_ra.is_ra = 1;
cur_ra.a0 = 0;
opt_code_list_i = 0;
}
// cur_ra.is_ra = 1;
while(1){
// printf("opt ra0_isused: %d ra1_isused: %d stack_pos_start: %d stack_pos_i: %d\n",ra0_isused,ra1_isused,stack_pos_start,stack_pos_i);
// printf("opt pc:%d code_list[pc].i.op: %d code_list_i: %d\n",pc,code_list[pc].i.op,code_list_i);
if(pc > code_list_i){
return;
}
switch(code_list[pc].i.op){
case I_PUSH:
// printf("I_PUSH is_ra: %d a0: %d\n",cur_ra.is_ra,cur_ra.a0);
stack[stack_pos_i].is_ra = cur_ra.is_ra;
stack[stack_pos_i].a0 = cur_ra.a0;
stack_pos_i--;
break;
case I_ENTER:
// printf("I_ENTER ra0_isused: %d ra1_isused: %d\n",ra0_isused,ra1_isused);
pc++;
if(ra0_isused == 0){
ra0_isused=1;
ra1_isused=0;
opt(lev+1,0,0);
}else if(ra0_isused == 1){
ra0_isused=1;
ra1_isused=1;
opt(lev+1,1,0);
}else if(ra1_isused == 1){
printf("ra1_isused == 1\n");exit(-1);
}else{
printf("ra0_isused: %d ra1_isused: %d\n",ra0_isused,ra1_isused);exit(-1);
}
break;
case I_EXIT:
// printf("I_EXIT\n");
// stack_pos_i++;
// printf("I_EXIT is_ra:%d a0:%d\n",stack[stack_pos_i].is_ra,stack[stack_pos_i].a0);
// cur_ra.is_ra = stack[stack_pos_i].is_ra;
// cur_ra.a0 = stack[stack_pos_i].a0;
return;
break;
case I_LOAD_A0:
// printf("I_LOAD X%d\n",code_list[pc].i.a0);
cur_ra.is_ra = 0;
cur_ra.a0 = code_list[pc].i.a0;
break;
case I_AND1_A0:
stack_pos_i++;
// printf("I_AND1 cur_ra.is_ra: %d cur_ra.a0: %d stack_pos_i: %d stack[stack_pos_i].is_ra: %d\n",cur_ra.is_ra,cur_ra.a0,stack_pos_i,stack[stack_pos_i].is_ra);
if(cur_ra.is_ra == 0 && stack[stack_pos_i].is_ra == 0){
// a0 && a1
if(ra_i == 0){
opt_code_list[opt_code_list_i].i.op = I_AND2_RA0_X_X;
opt_code_list[opt_code_list_i].i.a0 = cur_ra.a0;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra0 = X%d && X%d\n",cur_ra.a0,stack[stack_pos_i].a0);
} else if(ra_i == 1){
opt_code_list[opt_code_list_i].i.op = I_AND2_RA1_X_X;
opt_code_list[opt_code_list_i].i.a0 = cur_ra.a0;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra1 = X%d && X%d\n",cur_ra.a0,stack[stack_pos_i].a0);
}
opt_code_list_i++;
}else if(cur_ra.is_ra == 1 && stack[stack_pos_i].is_ra == 0){
if(ra_i == 0){
if(cur_ra.a0 == 0){
opt_code_list[opt_code_list_i].i.op = I_AND2_RA0_RA0_X;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra0 = ra0 && X%d\n",stack[stack_pos_i].a0);
}else if(cur_ra.a0 == 1){
opt_code_list[opt_code_list_i].i.op = I_AND2_RA0_RA1_X;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra0 = ra1 && X%d\n",stack[stack_pos_i].a0);
}
} else if(ra_i == 1){
if(cur_ra.a0 == 0){
opt_code_list[opt_code_list_i].i.op = I_AND2_RA1_RA0_X;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra1 = ra0 && X%d\n",stack[stack_pos_i].a0);
}else if(cur_ra.a0 == 1){
opt_code_list[opt_code_list_i].i.op = I_AND2_RA1_RA1_X;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra1 = ra1 && X%d\n",stack[stack_pos_i].a0);
}
}
opt_code_list_i++;
}else if(cur_ra.is_ra == 1 && stack[stack_pos_i].is_ra == 1){
if(ra_i == 0){
if(cur_ra.a0 == 0){
if(stack[stack_pos_i].a0 == 0){
// opt_code_list[opt_code_list_i].i.op = I_AND2_RA0_RA0_RA0;
printf("ra0 = ra0 && ra0\n");exit(-1);
}else if(stack[stack_pos_i].a0 == 1){
opt_code_list[opt_code_list_i].i.op = I_AND2_RA0_RA0_RA1;
}
printf("ra0 = ra0 && ra%d\n",stack[stack_pos_i].a0);
}else if(cur_ra.a0 == 1){
if(stack[stack_pos_i].a0 == 1){
// opt_code_list[opt_code_list_i].i.op = I_AND2_RA0_RA0_RA0;
printf("ra0 = ra1 && ra1\n");exit(-1);
}else if(stack[stack_pos_i].a0 == 0){
opt_code_list[opt_code_list_i].i.op = I_AND2_RA0_RA1_RA0;
}
printf("ra0 = ra1 && ra%d\n",stack[stack_pos_i].a0);
}
opt_code_list_i++;
} else if(ra_i == 1){
if(cur_ra.a0 == 0){
opt_code_list[opt_code_list_i].i.op = I_AND2_RA1_RA0_X;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra1 = ra0 && X%d\n",stack[stack_pos_i].a0);
}else if(cur_ra.a0 == 1){
opt_code_list[opt_code_list_i].i.op = I_AND2_RA1_RA1_X;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra1 = ra1 && X%d\n",stack[stack_pos_i].a0);
}
opt_code_list_i++;
}
}
cur_ra.is_ra = 1;
cur_ra.a0 = ra_i;
break;
case I_OR1_A0:
stack_pos_i++;
// printf("I_OR1 cur_ra.is_ra: %d cur_ra.a0: %d stack_pos_i: %d stack[stack_pos_i].is_ra: %d\n",cur_ra.is_ra,cur_ra.a0,stack_pos_i,stack[stack_pos_i].is_ra);
if(cur_ra.is_ra == 0 && stack[stack_pos_i].is_ra == 0){
// a0 || a1
if(ra_i == 0){
opt_code_list[opt_code_list_i].i.op = I_OR2_RA0_X_X;
opt_code_list[opt_code_list_i].i.a0 = cur_ra.a0;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra0 = X%d || X%d\n",cur_ra.a0,stack[stack_pos_i].a0);
} else if(ra_i == 1){
opt_code_list[opt_code_list_i].i.op = I_OR2_RA1_X_X;
opt_code_list[opt_code_list_i].i.a0 = cur_ra.a0;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra1 = X%d || X%d\n",cur_ra.a0,stack[stack_pos_i].a0);
}
opt_code_list_i++;
}else if(cur_ra.is_ra == 1 && stack[stack_pos_i].is_ra == 0){
if(ra_i == 0){
if(cur_ra.a0 == 0){
opt_code_list[opt_code_list_i].i.op = I_OR2_RA0_RA0_X;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra0 = ra0 || X%d\n",stack[stack_pos_i].a0);
}else if(cur_ra.a0 == 1){
opt_code_list[opt_code_list_i].i.op = I_OR2_RA0_RA1_X;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra0 = ra1 || X%d\n",stack[stack_pos_i].a0);
}
opt_code_list_i++;
} else if(ra_i == 1){
if(cur_ra.a0 == 0){
opt_code_list[opt_code_list_i].i.op = I_OR2_RA1_RA0_X;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra1 = ra0 || X%d\n",stack[stack_pos_i].a0);
}else if(cur_ra.a0 == 1){
opt_code_list[opt_code_list_i].i.op = I_OR2_RA1_RA1_X;
opt_code_list[opt_code_list_i].i.a1 = stack[stack_pos_i].a0;
printf("ra1 = ra1 || X%d\n",stack[stack_pos_i].a0);
}
opt_code_list_i++;
}
}else if(cur_ra.is_ra == 1 && stack[stack_pos_i].is_ra == 1){
if(ra_i == 0){
if(cur_ra.a0 == 0){
if(stack[stack_pos_i].a0 == 0){
// opt_code_list[opt_code_list_i].i.op = I_OR2_RA0_RA0_RA0;
printf("ra0 = ra0 || ra0\n");exit(-1);
}else if(stack[stack_pos_i].a0 == 1){
opt_code_list[opt_code_list_i].i.op = I_OR2_RA0_RA0_RA1;
}
printf("ra0 = ra0 || ra%d\n",stack[stack_pos_i].a0);
}else if(cur_ra.a0 == 1){
if(stack[stack_pos_i].a0 == 1){
// opt_code_list[opt_code_list_i].i.op = I_OR2_RA0_RA1_RA1;
printf("ra0 = ra1 || ra1\n");exit(-1);
}else if(stack[stack_pos_i].a0 == 0){
opt_code_list[opt_code_list_i].i.op = I_OR2_RA0_RA1_RA0;
}
printf("ra0 = ra1 || ra%d\n",stack[stack_pos_i].a0);
}
opt_code_list_i++;
} else if(ra_i == 1){
if(cur_ra.a0 == 0){
if(stack[stack_pos_i].a0 == 0){
// opt_code_list[opt_code_list_i].i.op = I_OR2_RA1_RA0_RA0;
printf("ra1 = ra0 || ra0\n");exit(-1);
}else if(stack[stack_pos_i].a0 == 1){
opt_code_list[opt_code_list_i].i.op = I_OR2_RA1_RA0_RA1;
}
printf("ra1 = ra0 || ra%d\n",stack[stack_pos_i].a0);
}else if(cur_ra.a0 == 1){
if(stack[stack_pos_i].a0 == 1){
// opt_code_list[opt_code_list_i].i.op = I_OR2_RA1_RA0_RA0;
printf("ra1 = ra1 || ra1\n");exit(-1);
}else if(stack[stack_pos_i].a0 == 0){
opt_code_list[opt_code_list_i].i.op = I_OR2_RA1_RA1_RA0;
}
printf("ra1 = ra1 || ra%d\n",stack[stack_pos_i].a0);
}
opt_code_list_i++;
}
}
cur_ra.is_ra = 1;
cur_ra.a0 = ra_i;
break;
case I_UIMP:
return;
break;
default:
break;
}
pc++;
}
}
// 只有vm需要存放在单片机里,只需要把opt_code_list数组从上位机传输到单片机里,vm函数只依赖opt_code_list数组。
static int vm(void){
int pc = 0;
int ra0 = 0;
int ra1 = 0;
static int x[6];
int run = 1;
x[0] = 0;
x[1] = 0;
x[2] = 2;
x[3] = 3;
x[4] = 4;
x[5] = 5;
x[6] = 6;
while(run){
printf("pc: %d ->",pc);
switch(opt_code_list[pc].i.op){
case I_PUSH:
case I_ENTER:
case I_EXIT:
case I_LOAD_A0:
case I_LOAD_A1:
case I_AND1_A0:
case I_AND1_A1:
case I_OR1_A0:
case I_OR1_A1:
printf("vm error\n");exit(-1);
break;
case I_AND2_RA0_X_X:
printf("RA0 = X%d && X%d\n",opt_code_list[pc].i.a0,opt_code_list[pc].i.a1);
ra0 = x[opt_code_list[pc].i.a0] && x[opt_code_list[pc].i.a1];
break;
case I_AND2_RA0_RA0_X:
printf("RA0 = RA0 && X%d\n",opt_code_list[pc].i.a1);
ra0 = ra0 && x[opt_code_list[pc].i.a1];
break;
case I_AND2_RA0_RA1_X:
printf("RA0 = RA1 && X%d\n",opt_code_list[pc].i.a1);
ra0 = ra1 && x[opt_code_list[pc].i.a1];
break;
case I_AND2_RA0_RA1_RA0:
printf("RA0 = RA1 && RA0\n");
ra0 = ra1 && ra0;
break;
case I_AND2_RA0_RA0_RA1:
printf("RA0 = RA0 && RA1\n");
ra0 = ra0 && ra1;
break;
case I_AND2_RA1_X_X:
printf("RA1 = X%d && X%d\n",opt_code_list[pc].i.a0,opt_code_list[pc].i.a1);
ra1 = x[opt_code_list[pc].i.a0] && x[opt_code_list[pc].i.a1];
break;
case I_AND2_RA1_RA0_X:
printf("RA1 = RA0 && X%d\n",opt_code_list[pc].i.a1);
ra1 = ra0 && x[opt_code_list[pc].i.a1];
break;
case I_AND2_RA1_RA1_X:
printf("RA1 = RA1 && X%d\n",opt_code_list[pc].i.a1);
ra1 = ra1 && x[opt_code_list[pc].i.a1];
break;
case I_AND2_RA1_RA1_RA0:
printf("RA1 = RA1 && RA0\n");
ra1 = ra1 && ra0;
break;
case I_OR2_RA0_X_X:
printf("RA0 = X%d || X%d\n",opt_code_list[pc].i.a0,opt_code_list[pc].i.a1);
ra0 = x[opt_code_list[pc].i.a0] || x[opt_code_list[pc].i.a1];
break;
case I_OR2_RA0_RA0_X:
printf("RA0 = RA0 || X%d\n",opt_code_list[pc].i.a1);
ra0 = ra0 || x[opt_code_list[pc].i.a1];
break;
case I_OR2_RA0_RA1_X:
printf("RA0 = RA1 || X%d\n",opt_code_list[pc].i.a1);
ra0 = ra1 || x[opt_code_list[pc].i.a1];
break;
case I_OR2_RA0_RA1_RA0:
printf("RA0 = RA1 || RA0\n");
ra0 = ra1 || ra0;
break;
case I_OR2_RA0_RA0_RA1:
printf("RA0 = RA0 || RA1\n");
ra0 = ra0 || ra1;
break;
case I_OR2_RA1_X_X:
printf("RA1 = X%d || X%d\n",opt_code_list[pc].i.a0,opt_code_list[pc].i.a1);
ra1 = x[opt_code_list[pc].i.a0] || x[opt_code_list[pc].i.a1];
break;
case I_OR2_RA1_RA0_X:
printf("RA1 = RA0 || X%d\n",opt_code_list[pc].i.a1);
ra1 = ra0 || x[opt_code_list[pc].i.a1];
break;
case I_OR2_RA1_RA1_X:
printf("RA1 = RA1 || X%d\n",opt_code_list[pc].i.a1);
ra1 = ra1 || x[opt_code_list[pc].i.a1];
break;
case I_OR2_RA1_RA1_RA0:
printf("RA1 = RA1 || RA0\n");
ra1 = ra1 || ra0;
break;
case I_OR2_RA1_RA0_RA1:
printf("RA1 = RA0 || RA1\n");
ra1 = ra0 || ra1;
break;
case I_UIMP:
printf("I_UIMP\n");
run = 0;
break;
default:
break;
}
pc++;
}
printf("RA0: %d RA1: %d\n",ra0,ra1);
return ra0;
}
离线
@xiaohui
感谢。
离线