mirror of
https://github.com/handsomezhuzhu/2025-yatcpu.git
synced 2026-02-20 20:10:14 +00:00
Added auto answer filler and updated anchors for lab2
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -11,3 +11,6 @@ target
|
|||||||
**/hello_z710-test
|
**/hello_z710-test
|
||||||
**/riscv-z710-v2020
|
**/riscv-z710-v2020
|
||||||
.Xil
|
.Xil
|
||||||
|
|
||||||
|
# autoans
|
||||||
|
misc/lab2_ans.yaml
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class Execute extends Module {
|
|||||||
)
|
)
|
||||||
io.if_jump_address := io.immediate + Mux(opcode === Instructions.jalr, io.reg1_data, io.instruction_address)
|
io.if_jump_address := io.immediate + Mux(opcode === Instructions.jalr, io.reg1_data, io.instruction_address)
|
||||||
io.mem_alu_result := alu.io.result
|
io.mem_alu_result := alu.io.result
|
||||||
// lab2(CLINTCSR)
|
//lab2(CLINTCSR)
|
||||||
/*
|
/*
|
||||||
io.csr_reg_write_data :=
|
io.csr_reg_write_data :=
|
||||||
*/
|
*/
|
||||||
|
|||||||
268
misc/autoans.py
Normal file
268
misc/autoans.py
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Code Auto-Filler Tool
|
||||||
|
|
||||||
|
This tool reads a YAML configuration file containing code snippets and operations,
|
||||||
|
then applies them to target files. It supports two main operations:
|
||||||
|
1. Adding import statements at the beginning of files
|
||||||
|
2. Inserting code blocks after specific anchor comments
|
||||||
|
"""
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
|
|
||||||
|
class CodeFiller:
|
||||||
|
def __init__(self, config_file: str, base_path: str = "."):
|
||||||
|
"""
|
||||||
|
Initialize the code filler.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config_file: Path to the YAML configuration file
|
||||||
|
base_path: Base directory for resolving relative target file paths
|
||||||
|
"""
|
||||||
|
self.config_file = config_file
|
||||||
|
self.base_path = Path(base_path).resolve()
|
||||||
|
self.config = self._load_config()
|
||||||
|
|
||||||
|
def _load_config(self) -> Dict:
|
||||||
|
"""Load and parse the YAML configuration file."""
|
||||||
|
try:
|
||||||
|
with open(self.config_file, 'r', encoding='utf-8') as f:
|
||||||
|
config = yaml.safe_load(f)
|
||||||
|
return config
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"Error: Configuration file '{self.config_file}' not found.")
|
||||||
|
sys.exit(1)
|
||||||
|
except yaml.YAMLError as e:
|
||||||
|
print(f"Error parsing YAML file: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def _resolve_target_path(self, target_file: str) -> Path:
|
||||||
|
"""Resolve the target file path relative to base path."""
|
||||||
|
if os.path.isabs(target_file):
|
||||||
|
return Path(target_file)
|
||||||
|
return self.base_path / target_file
|
||||||
|
|
||||||
|
def _backup_file(self, file_path: Path) -> None:
|
||||||
|
"""Create a backup of the original file."""
|
||||||
|
backup_path = file_path.with_suffix(file_path.suffix + '.backup')
|
||||||
|
if file_path.exists():
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as src:
|
||||||
|
with open(backup_path, 'w', encoding='utf-8') as dst:
|
||||||
|
dst.write(src.read())
|
||||||
|
print(f" Backup created: {backup_path}")
|
||||||
|
|
||||||
|
def _add_imports(self, lines: List[str], imports: List[str]) -> List[str]:
|
||||||
|
"""
|
||||||
|
Add import statements after the package declaration.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
lines: Original file lines
|
||||||
|
imports: List of import statements to add
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Modified file lines with imports added
|
||||||
|
"""
|
||||||
|
# Find the insertion point (after package declaration)
|
||||||
|
insert_index = 0
|
||||||
|
|
||||||
|
# Find package declaration
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
stripped = line.strip()
|
||||||
|
if stripped.startswith('package '):
|
||||||
|
insert_index = i + 1
|
||||||
|
break
|
||||||
|
|
||||||
|
# Insert imports after package declaration
|
||||||
|
new_lines = lines[:insert_index]
|
||||||
|
|
||||||
|
# Add the imports
|
||||||
|
for import_stmt in imports:
|
||||||
|
new_lines.append(import_stmt + '\n')
|
||||||
|
|
||||||
|
# Add a blank line after imports if there are remaining lines
|
||||||
|
if insert_index < len(lines):
|
||||||
|
new_lines.append('\n')
|
||||||
|
|
||||||
|
new_lines.extend(lines[insert_index:])
|
||||||
|
|
||||||
|
print(f" Added {len(imports)} import statement(s)")
|
||||||
|
|
||||||
|
return new_lines
|
||||||
|
|
||||||
|
def _insert_after_anchor(self, lines: List[str], anchor: str, code: str) -> List[str]:
|
||||||
|
"""
|
||||||
|
Insert code after a specific anchor comment.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
lines: Original file lines
|
||||||
|
anchor: The anchor comment to search for
|
||||||
|
code: The code block to insert
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Modified file lines with code inserted
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the anchor comment is not found in the file
|
||||||
|
"""
|
||||||
|
anchor_found = False
|
||||||
|
new_lines = []
|
||||||
|
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
new_lines.append(line)
|
||||||
|
|
||||||
|
if anchor.strip() in line.strip():
|
||||||
|
anchor_found = True
|
||||||
|
|
||||||
|
# Extract indentation from the anchor line
|
||||||
|
anchor_indent = ""
|
||||||
|
for char in line:
|
||||||
|
if char in [' ', '\t']:
|
||||||
|
anchor_indent += char
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
# Add the code block after the anchor with proper indentation
|
||||||
|
code_lines = code.strip().split('\n')
|
||||||
|
for code_line in code_lines:
|
||||||
|
# Apply anchor indentation to non-empty lines
|
||||||
|
if code_line.strip():
|
||||||
|
indented_line = anchor_indent + code_line
|
||||||
|
else:
|
||||||
|
indented_line = code_line # Keep empty lines as-is
|
||||||
|
new_lines.append(indented_line + '\n')
|
||||||
|
print(f" Inserted code after anchor: {anchor.strip()}")
|
||||||
|
|
||||||
|
if not anchor_found:
|
||||||
|
raise ValueError(f"Anchor '{anchor.strip()}' not found in file")
|
||||||
|
|
||||||
|
return new_lines
|
||||||
|
|
||||||
|
def _process_file(self, target_file: str, operations: Dict) -> None:
|
||||||
|
"""
|
||||||
|
Process a single target file with the specified operations.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
target_file: Path to the target file
|
||||||
|
operations: Dictionary containing imports and anchors operations
|
||||||
|
"""
|
||||||
|
file_path = self._resolve_target_path(target_file)
|
||||||
|
print(f"Processing: {file_path}")
|
||||||
|
|
||||||
|
# Check if file exists
|
||||||
|
if not file_path.exists():
|
||||||
|
print(f" Warning: Target file does not exist, creating new file")
|
||||||
|
file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
with open(file_path, 'w', encoding='utf-8') as f:
|
||||||
|
f.write('')
|
||||||
|
|
||||||
|
# Create backup
|
||||||
|
self._backup_file(file_path)
|
||||||
|
|
||||||
|
# Read the original file
|
||||||
|
with open(file_path, 'r', encoding='utf-8') as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
modified_lines = lines[:]
|
||||||
|
|
||||||
|
# Process imports
|
||||||
|
if 'imports' in operations and operations['imports']:
|
||||||
|
modified_lines = self._add_imports(modified_lines, operations['imports'])
|
||||||
|
|
||||||
|
# Process anchor insertions
|
||||||
|
if 'anchors' in operations and operations['anchors']:
|
||||||
|
for anchor, config in operations['anchors'].items():
|
||||||
|
if 'code' in config:
|
||||||
|
try:
|
||||||
|
modified_lines = self._insert_after_anchor(
|
||||||
|
modified_lines, anchor, config['code']
|
||||||
|
)
|
||||||
|
except ValueError as e:
|
||||||
|
raise ValueError(f"Failed to process file '{target_file}': {e}") from e
|
||||||
|
|
||||||
|
# Write the modified file
|
||||||
|
with open(file_path, 'w', encoding='utf-8') as f:
|
||||||
|
f.writelines(modified_lines)
|
||||||
|
|
||||||
|
print(f" ✓ File processed successfully")
|
||||||
|
|
||||||
|
def fill_codes(self, dry_run: bool = False) -> None:
|
||||||
|
"""
|
||||||
|
Execute the code filling process for all files in the configuration.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
dry_run: If True, only show what would be done without making changes
|
||||||
|
"""
|
||||||
|
if 'files' not in self.config:
|
||||||
|
print("Error: No 'files' section found in configuration")
|
||||||
|
return
|
||||||
|
|
||||||
|
if dry_run:
|
||||||
|
print("DRY RUN MODE - No files will be modified\n")
|
||||||
|
|
||||||
|
print(f"Base directory: {self.base_path}")
|
||||||
|
print(f"Configuration: {self.config_file}\n")
|
||||||
|
|
||||||
|
for target_file, operations in self.config['files'].items():
|
||||||
|
if dry_run:
|
||||||
|
print(f"Would process: {target_file}")
|
||||||
|
if 'imports' in operations:
|
||||||
|
print(f" Would add {len(operations['imports'])} import(s)")
|
||||||
|
if 'anchors' in operations:
|
||||||
|
print(f" Would process {len(operations['anchors'])} anchor(s)")
|
||||||
|
print()
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self._process_file(target_file, operations)
|
||||||
|
print()
|
||||||
|
except ValueError as e:
|
||||||
|
print(f" ✗ {e}")
|
||||||
|
print(f"\nExecution stopped due to configuration error.")
|
||||||
|
sys.exit(1)
|
||||||
|
except Exception as e:
|
||||||
|
print(f" ✗ Unexpected error processing file: {e}")
|
||||||
|
print(f"\nExecution stopped due to unexpected error.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if not dry_run:
|
||||||
|
print("Code filling completed!")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Automatically fill code into target files based on YAML configuration"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'config_file',
|
||||||
|
help='Path to the YAML configuration file'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-b', '--base-path',
|
||||||
|
default='.',
|
||||||
|
help='Base directory for resolving target file paths (default: current directory)'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-d', '--dry-run',
|
||||||
|
action='store_true',
|
||||||
|
help='Show what would be done without making any changes'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'-v', '--version',
|
||||||
|
action='version',
|
||||||
|
version='Code Auto-Filler 1.0.0'
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Create and run the code filler
|
||||||
|
filler = CodeFiller(args.config_file, args.base_path)
|
||||||
|
filler.fill_codes(dry_run=args.dry_run)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
43
misc/example_codes.yaml
Normal file
43
misc/example_codes.yaml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Example configuration file for code insertion
|
||||||
|
# Format: target_file -> operations
|
||||||
|
|
||||||
|
files:
|
||||||
|
# Example target file 1
|
||||||
|
"src/main/scala/MyModule.scala":
|
||||||
|
imports:
|
||||||
|
- "import chisel3.util._"
|
||||||
|
- "import chisel3.experimental._"
|
||||||
|
|
||||||
|
anchors:
|
||||||
|
"// INSERT_REGISTERS_HERE":
|
||||||
|
code: |
|
||||||
|
val regA = RegInit(0.U(32.W))
|
||||||
|
val regB = RegInit(0.U(32.W))
|
||||||
|
val counter = RegInit(0.U(8.W))
|
||||||
|
|
||||||
|
"// INSERT_LOGIC_HERE":
|
||||||
|
code: |
|
||||||
|
when(io.enable) {
|
||||||
|
regA := io.dataIn
|
||||||
|
counter := counter + 1.U
|
||||||
|
}.otherwise {
|
||||||
|
regA := 0.U
|
||||||
|
}
|
||||||
|
|
||||||
|
# Example target file 2
|
||||||
|
"src/test/scala/MyModuleTest.scala":
|
||||||
|
imports:
|
||||||
|
- "import chiseltest._"
|
||||||
|
- "import org.scalatest.flatspec.AnyFlatSpec"
|
||||||
|
|
||||||
|
anchors:
|
||||||
|
"// INSERT_TEST_CASE":
|
||||||
|
code: |
|
||||||
|
it should "handle basic operations" in {
|
||||||
|
test(new MyModule) { dut =>
|
||||||
|
dut.io.enable.poke(true.B)
|
||||||
|
dut.io.dataIn.poke(42.U)
|
||||||
|
dut.clock.step()
|
||||||
|
dut.io.dataOut.expect(42.U)
|
||||||
|
}
|
||||||
|
}
|
||||||
1
misc/requirements.txt
Normal file
1
misc/requirements.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
PyYAML>=6.0
|
||||||
Reference in New Issue
Block a user