{"id":21361620,"url":"https://github.com/phillbush/legv8","last_synced_at":"2026-01-02T15:50:16.735Z","repository":{"id":133377780,"uuid":"311204613","full_name":"phillbush/legv8","owner":"phillbush","description":"LEGv8 CPU implementation and some tools like a LEGv8 assembler","archived":false,"fork":false,"pushed_at":"2020-11-28T00:16:38.000Z","size":127,"stargazers_count":27,"open_issues_count":1,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-22T19:16:24.187Z","etag":null,"topics":["awk","hennessy","hennessy-and-patterson","legv8","legv8-arm","patterson","pipeline-cpu","pipeline-processor","single-cycle","single-cycle-processor","verilog"],"latest_commit_sha":null,"homepage":"","language":"Verilog","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phillbush.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-09T02:40:05.000Z","updated_at":"2024-11-10T05:05:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"0d8a39cc-4e06-4fbd-abb2-c5d6119940bc","html_url":"https://github.com/phillbush/legv8","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phillbush%2Flegv8","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phillbush%2Flegv8/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phillbush%2Flegv8/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phillbush%2Flegv8/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phillbush","download_url":"https://codeload.github.com/phillbush/legv8/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243835937,"owners_count":20355611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["awk","hennessy","hennessy-and-patterson","legv8","legv8-arm","patterson","pipeline-cpu","pipeline-processor","single-cycle","single-cycle-processor","verilog"],"created_at":"2024-11-22T06:10:40.940Z","updated_at":"2026-01-02T15:50:16.703Z","avatar_url":"https://github.com/phillbush.png","language":"Verilog","funding_links":[],"categories":[],"sub_categories":[],"readme":"LEGv8\n=====\n\nThis repository contains two implementations of a LEGv8 CPU;\nit also contains some tools written in AWK used to test the CPU:\na simple LEGv8 assembler and a verilog testbench generator.\nIt is the final project of the Computer Organization and Architecture\ncourse of the Computer Science department of the University of Brasilia.\n\nLEGv8 is a simple subset of the ARMv8 AArch64 architecture;\nit is a 64-bit architecture that uses 32-bit instructions.\nIt has 32 registers, each 64-bits wide, (one of them always zero).\nTo simplify the design, this CPU uses the Harvard memory architecture;\nthis architecture uses two memories: one for the program itself (the\ninstruction memory) and another for the data the program uses (the data memory).\nIt differs from the Von Neumann architecture in which there is a single memory.\n\nAll files are in public domain.\n\n\n## FILES\n\n* `CPU-pipelined`:   A pipelined implementation of a LEGv8 CPU, with hazard detection and forwarding.\n* `CPU-singlecycle`: A single-cycle implementation of a LEGv8 CPU.\n* `include`:         Headers defining constants such as bus sizes and opcodes.\n* `modules`:         Modules shared by all implementations.\n* `samples`:         Sample programs written in LEGv8 assembly.\n* `tools`:           AWK tools (an assembler and a testbench generator).\n\n\n## USAGE\n\n**Step 1: Assemble the program.**\nFirst, to test a CPU, a program should be assembled in order to be load into its memory.\n\nThe directory `samples/` contains simple programs that can be assembled\nwith the AWK assembler located in `tools/asm`.\nFor example, the following command assembles the program sumtwo.s,\nwhich sum the first two values in memory into the register X0.\n\n\t$ cd samples\n\t$ ../tools/asm sumtwo.s\n\nThis command generates two files: sumtwo.text and sumtwo.data.\nsumtwo.text contains the machine code of the program instructions.\nsumtwo.data contains the raw data used by the program.\n\nTo automate the process, the Makefile in the directory `samples/`\nassembles all programs and generate both files for each of them.\n\n\t$ cd samples\n\t$ make\n\n**Step 2: Generate the testbench.**\nTo test the CPU, a testbench should be generated to pulse the clock the CPU uses.\n\nThe directory `cpu-singlecycle/` contains the datapath for a single-cycle CPU.\nThe datapath is the main module of the CPU, that instantiate all other modules.\nIn this directory, run the testbench generator at `tools/tbgen` to generate a\ntestbench for this CPU.  The following command do this, but do not run it yet,\nwe'll improve this command with some arguments later.\n\n\t$ cd cpu-singlecycle\n\t$ ../tools/tbgen datapath.v \u003e testbench.v\n\nThis command will fail, since the datapath module needs some data in the\nfiles in the directory ../include.  To specify this directory, we need\nto add the following argument:\n\n\t-v incdir=../include\n\nThis command generates a file `testbench.v` that, when simulated,\nwill create a file called `testbench.vcd` containing the waveforms of the CPU.\nBut this waveform is useless, it only shows waves for the inputs controlled by the testbench,\nwhich are the clock and the reset signals.  To dump waveforms for more signals,\nwe need to set the dumplevel to 3: thus we will dump the signals of the testbench\nitself, the module under test (datapath.v) and the modules instanciated by the\nmodule under test.  The following argument do this\n\n\t-v dumplevel=3\n\nIn addition to the waveforms of the signals of the CPU, we can dump the contents\nof the data memory and the registers of the CPU at the end of the simulation.\nThe contents of the data memory are in the array `memdata.data`, and\nthe contents of the registers are in the array `registerfile.registers`.\nThe following arguments for `tools/tbgen` dump the contents of the data memory\ninto the file `memory.dump` and the contents of the registers into the file\n`registers.dump`.\n\n\tdump:registerfile.registers:registers.dump \\\n\tdump:memdata.data:memory.dump\n\nAssembling all arguments, we got the following command.\n\n\t$ cd cpu-singlecycle\n\t$ ../tools/tbgen -v incdir=../include \\\n\t                 -v dumplevel=3 \\\n\t                 dump:registerfile.registers:registers.dump \\\n\t                 dump:memdata.data:memory.dump \\\n\t                 datapath.v \\\n\t                 \u003etestbench.v\n\nTo automate this step, the Makefile in the directory `cpu-singlecycle/`\ncan generate the testbench for the datapath with the following command.\n\n\t$ cd cpu-singlecycle\n\t$ make testbench.v\n\n**Step 3: Run the simulation.**\nTo run the simulation, we must first run iverilog(1) to compile the sources\nof the datapath and the modules used by it (located at `../modules`).  Then,\nrun vvp(1) to do the simulation and generate the files `testbench.vcd` (which\ncontains the waveforms), `registers.dump` (which contains the contents of the\nregisters) and `memory.dump` (which contains the contents of the registers).\nThe following commands do it, it will generate the file `testbench`, which we\ncan delete after running vvp(1).\nBut don't run these commands yet, as they will fail.\n\n\t$ cd cpu-singlecycle\n\t$ iverilog -s testbench -o testbench testbench.v datapth.v ../modules/*.v\n\t$ vvp testbench \u003c/dev/null\n\t$ rm testbench\n\nThis command will fail because again we haven't specified the directory\ncontaining the files to include.  This command will also fail because we\nhaven't defined the contents of the memories.  We must define `TEXTFILE`\nto the file containing the contents of the program memory, and `DATAFILE`\nto the file containing the contents of the data memory.  Remember that we\nhave generated those files in the first step, by assembling the program we\nare testing.  The following command do all of this.\n\n\t$ cd cpu-singlecycle\n\t$ iverilog -DTEXTFILE=\\\"../samples/sumtwo.text\\\" \\\n\t           -DDATAFILE=\\\"../samples/sumtwo.data\\\" \\\n\t           -I../includes -s testbench -o testbench \\\n\t           testbench.v ../modules/*.v\n\t$ vvp testbench \u003c/dev/null\n\t$ rm testbench\n\nTo automate this step, the Makefile in the directory `cpu-singlecycle/`\ncan run the simulation with the following command.  We just need to set\nthe variable `PROG` to point to the correct program and make `sim` (simulation).\n\n\t$ cd cpu-singlecycle\n\t$ make PROG=sumtwo sim\n\n\n**Step 4: Check the results of the simulation.**\nTo check the waveform generated by the simulation, use the program gtkwave(1)\non the file `testbench.vcd`.  To check the contents of the registers and the\ndata memory, open the files `memory.dump` and `registers.dump` with your\nfavorite text editor.  Note that the file `memory.dump` contains one byte\nper line; while the file `registers.dump` contain one register (8 bytes)\nper line.\n\n**Step 5: Check the RTL netlist.**\nTo view the RTL netlist of the datapath (or any other module), we can use yosys(1).\n\nThe following command generates the file `netlist.png` with the RTL\nnetlist of the datapath module.  Note that we also need to define\n`TEXTFILE`, `DATAFILE` and declare the include directory.\n\n\t$ yosys -p \"read_verilog -DTEXTFILE=\\\"../samples/sumtwo.text\\\" \\\n\t            -DDATAFILE=\\\"../samples/sumtwo.data\\\" \\\n\t            -I../include \\\n\t            datapath.v ../modules/*; \\\n\t            hierarchy -check; \\\n\t            show -stretch -format png -prefix ./netlist datapath\"\n\nTo automate this step, the Makefile in the directory `cpu-singlecycle/`\ncan synthesizde the rtl netlist with the following command.\n\n\t$ cd cpu-singlecycle\n\t$ make PROG=sumtwo rtl\n\n\n**Notes.**\nTo run the simulation with another program, replace `sumtwo` in the\n`make` invocations with the program you assembled.  To run the simulation with\nanother CPU, go to a directory other than `cpu-singlecycle`.\n\n\n## INSTRUCTIONS\n\nCheck the directories `cpu-*` and `modules` for more information on\nthe modules that compose the CPUs.\n\nThe following is a list of LEGv8 instructions.\nInstructions that are checked are the ones supported by this implementation.\nMultiplication, division and floating-point operations are not supported yet.\n\n* [x] LSR\n* [x] LSL\n* [ ] MUL\n* [ ] SMULH\n* [ ] UMULH\n* [ ] SDIV\n* [ ] UDIV\n* [x] ADD\n* [x] SUB\n* [x] AND\n* [x] ORR\n* [x] EOR\n* [x] ANDS\n* [x] ADDS\n* [x] SUBS\n* [x] ADDI\n* [x] SUBI\n* [x] ANDI\n* [x] ORRI\n* [x] EORI\n* [x] ANDIS\n* [x] ADDIS\n* [x] SUBIS\n* [ ] FADDS\n* [ ] FADDD\n* [ ] FCMPS\n* [ ] FCMPD\n* [ ] FDIVS\n* [ ] FDIVD\n* [ ] FMULS\n* [ ] FMULD\n* [ ] FSUBS\n* [ ] FSUBD\n* [x] B\n* [x] BL\n* [x] BR\n* [x] CBZ\n* [x] CBNZ\n* [x] B.EQ\n* [x] B.NE\n* [x] B.LT\n* [x] B.LE\n* [x] B.GT\n* [x] B.GE\n* [x] B.LO\n* [x] B.LS\n* [x] B.HI\n* [x] B.HS\n* [x] B.MI\n* [x] B.PL\n* [x] B.VS\n* [x] B.VC\n* [ ] LDURB\n* [ ] LDURH\n* [ ] LDURSW\n* [x] LDUR\n* [ ] LDXR\n* [ ] STURB\n* [ ] STURH\n* [ ] STURW\n* [x] STUR\n* [ ] STXR\n* [ ] LDURS\n* [ ] LDURD\n* [ ] STURS\n* [ ] STURD\n* [x] MOVK\n* [x] MOVZ\n\nThe following is a list of pseudo instructions supported by the assembler.\n\n* [x] MOV\n* [x] CMP\n* [x] CMPI\n* [x] LDA\n\n\n## IMPLEMENTATION\n\nA simpler LEGv8 processor is described at the Computer Organization and Design book.\nThere are some differences between the processor implemented here and the one described in the book.\n\n* This implementation does not use an ALU Control Unit separated from the Main Control Unit.\n  Instead, the ALU Control signal is embedded in the Main Control Unit.\n\n* This implementation does not use the Shift Left 2 module separate from the Sign-Extend module.\n  Instead, the Shift Left 2 operation is done by the Sign-Extend module.\n\n* This implementation deals with all flags and flag-based branch instructions,\n  while the book's implementation only deals with the `zero` flag.\n  There is a Flags Register module which stores flags.\n  The ALU outputs a bus of flags to be set,\n  and the Control Unit outputs a control signal, called `SETFLAGS`, specifying whether the\n  flags output from the ALU should be saved on the Flags register.\n\n* This implementation deals with `MOV` instructions.\n  For this, it is needed a new module, called the MOV Unit module.\n\n* This implementation of the pipelined CPU decides whether to branch on the write-back stage.\n  The book, however, decides whether to branch one stage earlier, on the memory access stage.\n  It's done later here because we need the flags read from the Flags Register\n  (which is read on the memory access stage) in order to decide whether to branch.\n\n* The ALU control signal uses 6 bits rather than the 3 bits on the book.\n  The two first bits specifies whether to invert the two ALU operands;\n  the two following bits specifies whether and to which direction shift the result;\n  and the two last bits specifies one of the four operations to be executed.\n\n* The meaning of the bits of the control signal output by the Forwarding Unit\n  in this implementation is different from the book.\n  (See `include/forward.vh`).\n\nIn addition, the Control Unit implemented here outputs more control signals than the one on the book:\n\n* This implementation adds the control sign `SETFLAGS`.\n  This control signal decides whether to save the flags output from the ALU to the Flags Register.\n\n* This implementation adds the control signal `REG1LOC`.\n  This control signal decides whether the first register read from the Register File\n  is the register zero (`XZR`) or the register got from the instruction (`Rn`).\n  This is required because this ALU does no “Return B” operation;\n  instead, to return the second operand, we need to select the OR operation\n  between the given value (the second operand) and the contents of the `XZR` register,\n  returning thus the second operand.\n\n\n## TODO\n\n* [ ] Simplify aluop.\n* [x] Reuse the ALU to add the PC to the extended signal (and thus remove `modules/pcadder.v`).\n* [ ] Remove the need for passing the opcode from the ID stage to later stages\n      (maybe by increasing the number of control signals?).\n* [x] Add a mux from both `alures` and `movres` to a single `res`.\n* [ ] Add support for setting endianess.\n\n\n## SEE ALSO\n\nComputer Organization and Design: The Hardware/Software Interface ARM Edition\nby D. Patterson and J. Hennessy,\nMorgan Kaufmann, 2016.\nISBN: 978-012-8017333.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphillbush%2Flegv8","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphillbush%2Flegv8","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphillbush%2Flegv8/lists"}