adumont / hrm-cpu Goto Github PK
View Code? Open in Web Editor NEWHuman Resource Machine - CPU Design #HRM
Home Page: https://twitter.com/i/moments/1017515777610649601
License: GNU General Public License v3.0
Human Resource Machine - CPU Design #HRM
Home Page: https://twitter.com/i/moments/1017515777610649601
License: GNU General Public License v3.0
Index of position of FIFOs in GUI starts at 1 to 16. Should show 0 to 15.
Once INBOX is transformed into a FIFO, see #1 , plug a UART-RX to INBOX, so we can interact with the CPU (feed items).
That will allow us to plug a UART-RX to the FIFO.
Also modify the CPU FSM so that when in state DECODE, when Instr=INBOX & empty=1 , next_state <= DECODE (that is: stay in the same state until something arrives in INBOX)
https://stackoverflow.com/questions/36852808/modify-ice40-bitstream-to-load-new-block-ram-content
that would modify the workflow:
icebram --> random mem_fake.hex & prog_fake.hex files (will be replaced later) [only once, stored in source?]
for each board, but common for all level:
yosys .v --> .bliff
arachne-pnr lif --> board_generic.pnr
for each level:
icebram mem_fake.hex mem_[level].hex < board_generic.pnr > tmp.pnr
icebram prog_fake.hex mem_[level].hex < tmp.pnr > board_level.pnr
icepack board_level.pnr --> board_level.bin
It's basically a change in the /verilog/Makefile .
When OUTBOX is full, FSM waits (#12).
Confirm that when we pop an item out (cpu_out_rd=1):
Had to place some ugly lint_off inline comments in ram.v. Need to find a way to code it better so verilator lint won't complain about it:
/* verilator lint_off WIDTH */
if( ROMFILE ) $readmemh(ROMFILE, mem);
/* verilator lint_on WIDTH */
Verilator says:
%Warning-WIDTH: ram.v:23: Logical Operator IF expects 1 bit on the If, but If's VARREF 'ROMFILE' generates 104 bits.
Line 22 in ac54b4b
Seems that when pushing values to INBOX while it's full will overwrite the latest value of the FIFO.
I'd expect it to not do anything (sender should be carefull not to push if data is valuable, full means FIFO can't expect new data in)
yosys> fsm_detect
So that seems to imply that it's wrong to set a initialization value to the state register.
As a reference, it's true that Cummings papers don't show any init. value in the examples.
http://www.sunburst-design.com/papers/CummingsSNUG2003SJ_SystemVerilogFSM.pdf
Full script:
yosys>
read_verilog ControlUnit.v
proc; opt; fsm -nomap
fsm_detect
fsm_extract
fsm_info
fsm_export -o ControlUnit.kiss2
BTW, we can draw the kiss2 file using graphviz, see https://stackoverflow.com/questions/32645965/fsm-export-using-yosys
Check this post on a VGA simulator (in gtk)
https://zipcpu.com/blog/2018/11/29/llvga.html
Some words are lower case in machine language output (BIN)
Example, see 8e:
00: E0 8e ; SET 142
02: 10 ; OUTBOX
"Instanciate" should be "instantiate".
Need a way to switch into prog mode via UART. (ver señales DTR o RTS)
When switching to prog mode, reset PC.
When in prog mode, all data received in Inbox is written sequentially (incressing PC) to PROG ram.
See this thread on FPGAwars :
https://groups.google.com/d/msgid/fpga-wars-explorando-el-lado-libre/CABqu7xqtcHW25OCdn7%2B5GCJP8J14xkJJHbxkthLfOk_ZT_89pg%40mail.gmail.com?utm_medium=email&utm_source=footer
I am thinking of implementing the logic in the FSM, as an alternative branch, that way I can reuse the control path and data path to/from RX (inbox with FIFO), and PROG.
Same as with INBOX.
Modify CPU FSM:
WHen in state DECODE, if INSTR = "OUTBOX", if OUBOX FIFO is full (? full == 1) then next_state <= DECODE (stay here until FIFO not full anymore)
will allow to plug a UART-TX to OUTBOX
After #5
For now, I'm only focusing on Direct Addressing mode. Indirect mode will require some changes in the Control Unit (FSM).
GUI will loop if INSTR=INBOX, & Inbox is empty & user press F4 (next INSTR)
FSM should wait when Instruction is Outbox, and Outbox is Full, until Outbox isn't full anymore. (remember Outbox will become a FIFO, that we'll plug to a UART-TX for example).
New instruction SET ; will set R to .
Allows to pass constants in programs.
For memory instructions, use the two unused bits to encode 3 values of the operand, so the instructions can be written in only 1 byte (instead of two that it should normally be)
For example COPYTO 0 (or 1 or 2) would fit in only 1 byte, encoding the operand (0, 1, or 2) in the two unused bits of the opcode.
That involves changes in the FSM (faster as we bypass the steps of reading the Operand).
Also involves changes in the assembler obviously.
check if true. if that's the case:
impact on
I want the Makefile to support env vars to build specific versions of the tools in the toolchain.
For example, YOSYS_VERSION for Yosys.
It would then do git checkout $YOSYS_VERSION
It could be a branch, a tag or a commit ID.
If no version specified, checkout master branch.
That combined with travis.yml env sections, it will run a build for every line.
env:
Build log --> https://travis-ci.org/adumont/hrm-cpu/builds/438284957
While building yosys:
[ 84%] Building techlibs/coolrunner2/coolrunner2_sop.o
[ 84%] Building techlibs/easic/synth_easic.o
[ 85%] Building techlibs/ecp5/synth_ecp5.o
clang-5.0: error: unable to execute command: Killed
clang-5.0: error: clang frontend command failed due to signal (use -v to see invocation)
[ 85%] Building techlibs/gowin/synth_gowin.o
clang version 5.0.0 (tags/RELEASE_500/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/clang-5.0.0/bin
clang-5.0: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script.
clang-5.0: error: unable to execute command: Killed
clang-5.0: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 5.0.0 (tags/RELEASE_500/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/clang-5.0.0/bin
clang-5.0: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script.
clang-5.0: error: unable to execute command: Killed
clang-5.0: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 5.0.0 (tags/RELEASE_500/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/clang-5.0.0/bin
clang-5.0: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script.
[ 86%] Building techlibs/greenpak4/synth_greenpak4.o
clang-5.0: error: unable to execute command: Killed
clang-5.0: error: clang frontend command failed due to signal (use -v to see invocation)
clang version 5.0.0 (tags/RELEASE_500/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/clang-5.0.0/bin
clang-5.0: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script.
In an hrm program, the operands (tile number) are written in decimal, but with the assembler we need to convert them to hex
Limitation in Logisim FSM, doesnt allow to stay in same state (wait here).
Review when implementing with Fizzim / Verilog.
In DECODE state, When ( Instr = INBOX AND empty = 1 ), FSM should stay in DECODE (until empty = 0).
For now I have added the extra step WAIT_INBOX to transition back back to DECODE, to reevaluate again.
Doesn't seem very eficient.
Have a look at TUG, testing framework for QT.
Could be fun?
$ make -C ROT13 -f ../tester.mk
make: Entering directory '/home/adumont/hrmcpu/verilog/test/ROT13'
../../../logisim/prog/assembler PROG >/dev/null && rm PROG.BIN
iverilog ../../ufifo.v ../../ALU.v ../../MEMORY.v ../../XALU.v ../../LEDS.v ../../RAND.v ../../ram.v ../../mem_wrapper.v ../../REG.v ../../IR.v ../../PROG.v ../../WAIT.v ../../PC.v ../../ControlUnit.v ../../hrmcpu.v ../../test/tester.v -DPROGRAM=\"program\" -DROMFILE=\"ram\" -DINBFILE=\"test00.in\" -DDUMPFILE=\"test00.lxt\" -o test00.ivl
../../mem_wrapper.v:45: warning: Port 4 (rst) of XALU expects 1 bits, got 32.
../../mem_wrapper.v:45: : Pruning (signed) 31 high bits of the expression.
../../mem_wrapper.v:60: warning: Port 4 (rst) of LEDS expects 1 bits, got 32.
../../mem_wrapper.v:60: : Pruning (signed) 31 high bits of the expression.
../../mem_wrapper.v:74: warning: Port 4 (rst) of RAND expects 1 bits, got 32.
../../mem_wrapper.v:74: : Pruning (signed) 31 high bits of the expression.
vvp test00.ivl -lxt > test00.test_out
grep "TX OUT:" test00.test_out | awk '{ print $4 }' | diff -q test00.out - >/dev/null && \
( touch test00.check; printf "%b" "\033[0;32mROT13: Test [test00] OK\033[m\n" ) || \
( printf "%b" "\033[0;31mROT13: Test [test00] FAILED\033[m\n" ; false )
ROT13: Test [test00] OK
ROT13: Success, all tests passed
rm test00.ivl test00.test_out
make: Leaving directory '/home/adumont/hrmcpu/verilog/test/ROT13'
hrm-cpu/logisim/prog/assembler
Line 19 in bd2f2c0
operand /A1 should decode to 0x01 no 0x00:
s//A1//1/g;
Add support for command line arguments/options, for example to load a specific program file at startup
The ALU can perform 6 operations depending on signal aluCtl:
aluCtl | Operation | Output |
---|---|---|
0x0 | R + M | aluOut |
0x1 | R - M | aluOut |
x0x | R = 0 ? | flag |
x1x | R < 0 ? | flag |
1x0 | M + 1 | aluOut |
1x1 | M - 1 | aluOut |
Clearly, aluCtl could be split in two, see below, and its bits reorganized (but it would mean change a lot of things and all the documentation and images...)
Do before starting with ALU.
aluCtl | Operation | Output |
---|---|---|
x00 | R + M | aluOut |
x01 | R - M | aluOut |
x10 | M + 1 | aluOut |
x11 | M - 1 | aluOut |
0xx | R = 0 ? | flag |
1xx | R < 0 ? | flag |
Add iverilog to toolchain :
Add some testbech in Verilator
Idea, count Presses (denounced) or events of the buttons, and read them with COPYFROM...?
default behaviour for mem is to be addressed by operand DATA obtained from PROG.
it would make more sense to have this by default (that is when srcA=0) rather than having to set srcA=1.
Line 80 in 5512ee3
Add this functionality to vhelper.py, shouldn't be too hard.
Add button & FSM logic to go Instruction by instruction in the CPU
Show the two buttons and the LEDs in the GUI
Doesn't substitute all labels in .BIN when used more than one.
Ex PROG:
init:
00: 00 ; INBOX
01: 90 00 ; JUMPZ init
03: 10 ; OUTBOX
04: 80 00 ; JUMP init
BIN generated:
v2.0 raw 00 90 00 10 80 init
At the moment, the MEMORY module is held inside the HRMCPU module. Would it be best to put it outside?
tester should start the test with reset active, then low, in order to force the initialization of the modules.
how many clocks?
Somehow allow the user to load a assembler file and the GUI would assemble it to machine language.
see how to call Python from within C and interchange data between both...
Implement a generic address register in ahead of ram.
Store address from Prog Memory to Address Register or retrieve Address from Memory to AR (indirect addressing)
Line 15 in 5512ee3
Just before an element change it's value (when it's going to be written to, like wR = 1 for ex), slightly change it's background color?
Line 19 in 66be341
Would be great to have some GUI for simulation where the user could:
Since the readme contains so much useful info, it is starting to get annoying to scroll top/down in order to search/compare the desired content. I suggest to use an static site generator (such as Hugo, Jekyll or Sphinx) to create a website and upload/deploy it to branch gh-pages
(for it to be served at adumont.github.io/hrm-cpu).
I think that Hugo is the best option, because it expects sources to be written in Markdown (which is already the case) and because it is a single static binary. However, Hugo produces HTML sites only.
Conversely, Sphinx allows to use the same sources to generate both a web site and a PDF report. See, for example, ghdl.rtfd.io and https://ghdl.readthedocs.io/_/downloads/en/latest/pdf/. Although Markdown sources can be used, Sphinx is primarily meant for reStructuredText sources. See gohugoio/hugo#6332 (comment).
Moreover, it is straightforward to have a GitHub Actions automatically build and update the site after each commit is pushed. For example:
Although I cannot decide which tool or theme to use for you, I'd be glad to help you set up the CI job.
Add formal verification...
Help wanted for this one.
HW tests are run from python, would make sense to do the same with sw tests?
Maybe Python --> Verilator? (instead of iverilog testbench?) --> rewrite the testbench?
Also programmed tests instead of static tests like now?
Static tests: test.in / test.out are written to files, beforehand.
Programmed tests I mean I would write something like
for example, test for A*B, 15 rounds with random values:
for i in range(15)
a=random(10)
b=random(25)
in.append(a)
in.append(b)
out.append(a*b)
runTest("mul",in,out)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.