diff --git a/CMakeLists.txt b/CMakeLists.txt index 98b87ab..a56e9a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD 20) find_package(Boost 1.81 COMPONENTS program_options REQUIRED) -add_executable(lasm +add_executable(svrasm src/main.cpp src/lexer/Token.cpp src/lexer/Lexer.cpp @@ -25,4 +25,4 @@ add_executable(lasm src/codegen/CodegenObserver.cpp ) -target_link_libraries(lasm Boost::program_options) \ No newline at end of file +target_link_libraries(svrasm Boost::program_options) \ No newline at end of file diff --git a/src/codegen/CodegenObserver.cpp b/src/codegen/CodegenObserver.cpp index 93d80b0..77432a7 100644 --- a/src/codegen/CodegenObserver.cpp +++ b/src/codegen/CodegenObserver.cpp @@ -3,8 +3,7 @@ // #include "CodegenObserver.h" -#include -#include +#include CodegenObserver::CodegenObserver(const Node &node, std::vector &output_string) : PostfixObserver(node), output_string(output_string) {} @@ -13,12 +12,13 @@ void CodegenObserver::action(const Node &node) { const uint8_t dec = node.compile(); const uint8_t INVALID = -1; + // TODO: Don't do the conversion to binary here, but in generator module if (dec != INVALID) { // uint8_t is always interpreted as char, so cast to uint32_t - const std::string hex = (boost::format("%x") % static_cast(dec)).str(); - if (hex.empty() || hex.size() > 2) { + const std::string bin = std::bitset<8>(dec).to_string(); + if (bin.empty() || bin.size() > 8) { throw "Compile Error: Resulting instruction has invalid size!"; } - output_string.push_back(hex.length() == 2 ? hex : "0" + hex); + output_string.push_back(bin); } } diff --git a/src/main.cpp b/src/main.cpp index 94e62fd..8d55a7a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,19 +1,19 @@ -#include +#include "ast/Node.h" +#include "codegen/CodegenObserver.h" +#include "codegen/PrintObserver.h" +#include "lexer/Lexer.h" +#include "parser/Parser.h" +#include +#include #include +#include +#include #include #include -#include -#include -#include -#include "lexer/Lexer.h" -#include "ast/Node.h" -#include "parser/Parser.h" -#include "codegen/PrintObserver.h" -#include "codegen/CodegenObserver.h" namespace po = boost::program_options; -auto read(const std::string& input_file, std::string &input_string) -> bool { +auto read(const std::string &input_file, std::string &input_string) -> bool { std::ifstream ifs; ifs.open(input_file, std::ios_base::in); if (!ifs) { @@ -54,6 +54,7 @@ auto parse(std::vector &tokens) -> std::unique_ptr { return std::move(parser.parse()); } +// TODO: Modularize the output generation, I want different generators for different formats auto write(const std::string &output_file, const std::vector &output_string) -> bool { if (output_string.size() > 255) { std::cout << "Program too large!" << std::endl; @@ -67,22 +68,26 @@ auto write(const std::string &output_file, const std::vector &outpu return false; } - ofs << "v3.0 hex words addressed"; - for (uint32_t i = 0; i <= 255; ++i) { - if (i % 16 == 0) { - ofs << std::endl; - // Print Address - std::string address = (boost::format("%x") % i).str(); - ofs << (address == "0" ? "00" : address) << ": "; - } + ofs << "`default_nettype none\n\n" + << "module ROM(\n" + << " input var logic[7:0] address,\n" + << " output var logic[7:0] dataout\n" + << ");\n\n" + + << " always @(address) case (address)\n"; + + for (uint32_t i = 0; i <= 255; ++i) { if (i < output_string.size()) { - ofs << output_string[i] << " "; - } else { - ofs << "00 "; + ofs << " case 8'b" << std::bitset<8>(i).to_string() << ": dataout = 8'b" << output_string[i] << ";\n"; } } + ofs << " default: dataout = 8'b00000000;\n" + << " endcase\n\n" + + << "endmodule" << std::endl; + ofs.flush(); ofs.close(); return true; @@ -91,10 +96,7 @@ auto write(const std::string &output_file, const std::vector &outpu auto main(int argc, char **argv) -> int { // Argument parsing straight from the Boost manual: https://www.boost.org/doc/libs/1_60_0/doc/html/program_options/tutorial.html po::options_description desc("Allowed options"); - desc.add_options() - ("help,h", "Show this help message") - ("input,i", po::value(), "Input file") - ("output,o", po::value(), "Output file"); + desc.add_options()("help,h", "Show this help message")("input,i", po::value(), "Input file")("output,o", po::value(), "Output file"); po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm);