Re: [quirks-uvm-devel] One more program
Status: Pre-Alpha
Brought to you by:
teodor
From: Sergei L. <se...@mo...> - 2002-04-01 21:03:04
|
Hello. > I got the flex, bison and libraries. OK. Let me know if you get any troubles with adding it to the MSVC++ build process. > I am compiling the *.ua with ua.exe. Is this correct? Exactly. `ua' stays for "UVM assembler". The `au' tool is a disassembler. You can view *.ru files with it in the original form. About the first (CtoF) program. It mainly correct. But I haven't catch some error in your previous letter (and you have repeated it). When we define auMul (a b c) it means: c = a * b; And when we define auSum (a b c) it means: c = a + b; When we define auMul (a/out B/in C/in) think like it is equation with unknown a: C = a * B, i.e.: a = C / B. So, the positions of operands in your divisions and subtractions should be changed (We have got 10/(18 * C) instead of 18 * C / 10). In your second example I've found some errors (besides of described above) on topics I haven't good explained yet. Each AU (au module: auSum, auMul) can be (for each procedure) in the single instance. I.e., we can't have two auMul in the same procedure (but auMul, au2Mul, au3Mul). Think about AUs as real electronic devices (procedure scoped). When we say: "map auMul[2] on some register" that means the first multiplier, when we say "map au2Mul[2] on another register" that means the second one. But we cant say "map auMul[2] on the register A and on the register B" (only one real register should be in the mapping relation). Let's I explain the advantage of such approach. Let's see on expression A * B * C. Now we oblige to use intermediate register to store value of A * B i.e.: -- lv[0] = A, lv[1] = B, lv[2] = C, lv[3] = (B * C), fp[0] - the result type ~Mul is <int32/in int32/in int32/out stu>; -- (you can use -- aliases for types). declare map auMul is ~Mul; au2Mul is ~Mul; map is (auMul[0], lv[0]) (auMul[1], lv[1]) (auMul[2], lv[3]) (au2Mul[0], lv[3]) (au2Mul[1], lv[2]) (auMul[2], fp[0]) end map; But it is not our goal. It is temporary stage in movement to more power mapping: declare map auMul is ~Mul; au2Mul is ~Mul; map is (auMul[0], lv[0]) (auMul[1], lv[1]) (auMul[2], au2Mul[0]) -- attach 2 output of auMul to 0 input of au2Mul (au2Mul[1], lv[2]) (auMul[2], fp[0]) end map; We will be able use it if we will accept the principle of AU (Arithmetic Unit) as a device, not AU as a function (or predicate). And with the second variant we get new combined device. I try generate code by patterns which include several devices in such connections. In many cases we can do more accurate register allocation. So, let's think about temporary registers as about temporary solution. The second moment is the use of act. I already wrote: > (When you invoke `act' the according map calls all defined AUs from > top to bottom. It is not on principle to which AU from this map you > point with act. Ideally we need only one map and an algorithm for > finding AUs which involved in operation ... Well, I mean this fragment from your code: > exit @Loop when not lv[0]; > * auMul; > * auSum; > lv[5] <- lv[2]; We don't need two acts. The *auMul will invoke all AUs declared in the same map to work. They will perform their action according to definition order: > declare map > -- Get access to two registers of > incrementer/decrementer > auInc is <int32/in int32/out stu>; > > -- Three ports of multiplier > auMul is <int32/in int32/in int32/out stu>; > au2Mul is <int32/out int32/in int32/in stu>; > auSum is <int32/in int32/in int32/out > stu>; > > map is i.e.: auInc, then auMul, then au2Mul, then auSum. In this order each module will perform its action. So, the map is monolithic entity. You can't call separate modules from it. You can refer to all of its modules by pointing any of them, i.e: *auMul; or *auSum; All variants are equal. OK. Some trifles at the end. 1. What is auCmp with to channels (in out) ? If it is new module you enter please comment what it does. 2. `endif' should be `end if'. 3. Why you doesn't use `else' parts? It is faster. P.S, Now I prepare a general schema of the assembler backend we will implement. I will finish it in a few days. But you could start working in this area (if you wish). The task is: Get a command reference book for any of these processors: Intel 386, 486 or Pentium. Write down all registers besides of those which is used for special operations like protected mode control etc. Try find several groups (they can be intersected). For example: - registers which can be used as any argument in big part of arithmetic operation (general purpose); - accumulator (some operations can work only with it); - registers for counter in rotation operations; ... The main rule is: all register in one groups are fully replaceable in operations. I can use any of these registers in some concrete place. So, this classification should be base on a place where particular set (group) of registers can be use (example of such "place": the first operand of a `mul' operation). Give a simple name (identifier) to each group. We will use such information as a part of description for a target processor. -- Thanks, Sergei |